package org.mikrosopht.movievote.client;

import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONException;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.Widget;

public class VoteWidget extends Composite implements MouseListener {

  private static final String PLUSVOTE_URL = "/vote/plusvote/json";
  private static final String MINUSVOTE_URL = "/vote/minusvote/json";
  private static final String PLUS_ON_IMG = MovieVoteConstants.IMAGE_PATH_URL + "/plus_on.png";
  private static final String PLUS_OFF_IMG = MovieVoteConstants.IMAGE_PATH_URL + "/plus_off.png";
  private static final String MINUS_ON_IMG = MovieVoteConstants.IMAGE_PATH_URL + "/minus_on.png";
  private static final String MINUS_OFF_IMG = MovieVoteConstants.IMAGE_PATH_URL + "/minus_off.png";

  private Image plusOnImage = new Image(PLUS_ON_IMG);
  private Image plusOffImage = new Image(PLUS_OFF_IMG);
  private Image minusOnImage = new Image(MINUS_ON_IMG);
  private Image minusOffImage = new Image(MINUS_OFF_IMG);

  private String movieName;
  private Grid voteGrid = new Grid(1, 3);
  private VoteWidgetEventReceiver receiver;
  
  public VoteWidget(String movieName, boolean hasPlusVoted, boolean hasMinusVoted, VoteWidgetEventReceiver receiver) {
    this.movieName = movieName;
    this.receiver = receiver;
    if (hasPlusVoted) {
      voteGrid.setWidget(0, 0, plusOnImage);
      voteGrid.setWidget(0, 1, minusOffImage);
    } else if (hasMinusVoted) {
      voteGrid.setWidget(0, 0, plusOffImage);
      voteGrid.setWidget(0, 1, minusOnImage);
    } else {
      voteGrid.setWidget(0, 0, plusOffImage);
      voteGrid.setWidget(0, 1, minusOffImage);
    }
    plusOnImage.addMouseListener(this);
    plusOffImage.addMouseListener(this);
    minusOnImage.addMouseListener(this);
    minusOffImage.addMouseListener(this);
    initWidget(voteGrid);
  }

  public void onMouseEnter(Widget sender) {
    sender.addStyleName("clickable");
  }
  public void onMouseLeave(Widget sender) {
    sender.removeStyleName("clickable");
  }
  public void onMouseMove(Widget sender, int x, int y) {
  }
  public void onMouseUp(Widget sender, int x, int y) {
  }

  public void onMouseDown(Widget sender, int x, int y) {
    String url = null;
    if (sender == plusOnImage || sender == minusOffImage) {
      url = URL.encode(MINUSVOTE_URL + "/" + movieName + "/");
      if (sender == plusOnImage) {
        voteGrid.setWidget(0, 0, plusOffImage);
      } else if (sender == minusOffImage) {
        if (voteGrid.getWidget(0, 0) == plusOnImage) {
          voteGrid.setWidget(0, 0, plusOffImage);
        } else {
          voteGrid.setWidget(0, 1, minusOnImage);
        }
      }
    } else if (sender == plusOffImage || sender == minusOnImage) {
      url = URL.encode(PLUSVOTE_URL + "/" + movieName + "/");
      if (sender == plusOffImage) {
        if (voteGrid.getWidget(0, 1) == minusOnImage) {
          voteGrid.setWidget(0, 1, minusOffImage);
        } else {
          voteGrid.setWidget(0, 0, plusOnImage);
        }
      } else if (sender == minusOnImage) {
        voteGrid.setWidget(0, 1, minusOffImage);
      }
    }
    if (url != null) {
      RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
      try {
        builder.sendRequest(null, new VoteHandler());
      } catch (RequestException e) {
        Window.alert("Couldn't retrieve JSON: " + e);
      }
    }
  }

  private class VoteHandler implements RequestCallback {
    public void onError(Request request, Throwable exception) {
      Window.alert("Couldn't retrieve JSON: " + exception);
    }

    public void onResponseReceived(Request request, Response response) {
      if (response.getStatusCode() == 200) {
        try {
          Movie movie = MovieDataSourceTableModel.parseJsonToMovie(JSONParser.parse(response.getText()).isObject());
          receiver.onVoteChange(movie);
        } catch (JSONException e) {
          MovieVote.redirectToLogin();
        }
      } else {
        Window.alert("Couldn't retrieve JSON: " + response.getStatusText());    
      }
    }
  }
}
